import axios from "axios";
import qs from "qs";
import NProgress from "nprogress";
import { clone, isPlainObject, isString, parseUrl } from "xe-utils";
import store from "@/store";
import router from "@/router";
import { messageError } from "@/util/element-ui";
import { filterParams } from "@/util";

const instance = axios.create({
  baseURL: process.env.VUE_APP_API_ROOT,
  timeout: 60000,
});

instance.interceptors.request.use((config) => {
  if (config.url !== "/workbench/message/list") {
    NProgress.start();
  }
  const params = parseUrl(window.location.href);
  if (params.hashQuery && params.hashQuery.token) {
    config.headers["Token"] = params.hashQuery.token;
  }
  if (store.state.user.token) {
    config.headers["Authorization"] = `Bearer ${store.state.user.token}`;
  } else {
    if (config.url === "/oauth/logout") {
      config.headers["Authorization"] = `Bearer ${config.data.token}`;
    } else {
      config.headers["Authorization"] = "Basic b3BlbmlkOm9wZW5pZF9zZWNyZXQ=";
    }
  }

  ["data", "params"].forEach((item) => {
    if (config[item]) {
      //这里会过滤为空、undefined 和 前端私有的 key(使用__前缀命名)
      config[item] = filterParams(clone(config[item], true));
    }
  });

  //如果是get请求，且params是数组类型如arr=[1,2]，则转换成arr=1&arr=2
  if (["get", "post"].includes(config.method)) {
    config.paramsSerializer = function (params) {
      return qs.stringify(params, { arrayFormat: "repeat" });
    };
  }

  return config;
}, onRejected);

instance.interceptors.response.use((res) => {
  NProgress.done();
  // tips: 如果要导出，请在此处增加接口路径
  const arr = [
    "/system/downloadFile",
    "/system/previewFile",
    "/project/projectprogress/exportPreProject",
    "/project/preProject/export",
    "/project/demolitionProject/export",
    "/implementation/projectDetail/export",
    "/project/middleProject/export",
    "/project/projectprogress/exportDemolitionProject",
    "/project/projectprogress/exportForImplementationProject",
    "/parkChargingStation/export",
    "/parkInfo/export",
    "/parkHospital/export",
    "/parkPublicBuilding/export",
    "/parkOldResidentialArea/export",
    "/parkPublic/export",
    "/meetingManagement/export",
    "/projectPlanning/export",
    "/investmentEstimation/export",
    "/designEstimate/export",
    "/constructionDrawingBudget/export",
    "/projectContract/export",
    "/projectSchedule/export",
    "/attendanceRecord/month/export",
    "/constructionWeeklyReport/export", //施工周报导出
    "/constructionMonthReport/export", //施工月报导出
    "/supervisionWeeklyReport/export", //监理周报导出
    "/supervisionMonthReport/export", //监理月报导出
    "/correctiveRequests/export", // 质量整改单导出、安全整改单导出
    "/qualityInspection/export", // 质量巡检导出、安全巡检导出
    "/preliminaryProcedure/export", // 前期手续导出
    "/visaForm/export", //签证单导出
    "/fileUpload/export", //文件上传导出
    "/legalContract/export",
    "/lawAuditCorrection/export", // 法务整改单导出
    "/lawLitigationProgress/export", //诉讼进度导出
  ];
  const resData = arr.includes(parseUrl(res.config.url).pathname) ? res : res.data;
  const { data, code, msg } = resData;
  if (code === 200) {
    return data ?? resData;
  }
  if (code) {
    handleException(msg, code);
    return Promise.reject(new Error(JSON.stringify({ url: res.config.url, msg })));
  }
  return resData;
}, onRejected);

function handleException(message, code) {
  if (code === 502) {
    messageError("系统正在部署，请勿操作。");
  } else {
    messageError(message);
  }
  switch (code) {
    case 401:
      setTimeout(() => {
        store.dispatch("user/logout");
        router.replace({
          path: "/login",
          query: {
            redirect: router.currentRoute.fullPath,
          },
        });
      }, 2000);
      break;
    case 404:
      if (["production", "uat"].includes(process.env.VUE_APP_ENV)) {
        router.replace({
          path: "/404",
          query: {
            redirect: router.currentRoute.fullPath,
          },
        });
      }
      break;
    default:
      break;
  }
}

function onRejected(err) {
  NProgress.done();
  const { response, message } = err;
  if (response && response.data) {
    const { status, data } = response;
    handleException(data.msg || data.message || data.error_description || data.error || message, status);
    return Promise.reject(err);
  } else {
    messageError(message);
    return Promise.reject(err);
  }
}

export default instance;
function _get({ url, pathParams, params, config = {} }) {
  if (pathParams) {
    url = `${url}/${Object.values(pathParams).join("/")}`;
  }
  return instance({ method: "get", url, params, ...config });
}

/**
 *
 * @param {(string|Object)} arg1 url or config
 * @param {Object} [params]
 * @param {import("axios").AxiosRequestConfig} [config]
 * @param {string} arg1.url
 * @param {Object} [arg1.pathParams]
 * @param {Object} [arg1.params]
 */
export function get(arg1, params, config) {
  if (isString(arg1)) {
    return _get({ url: arg1, params, config });
  } else if (isPlainObject(arg1)) {
    return _get(arg1);
  } else {
    throw new Error("PARAMS ERROR");
  }
}

/**
 * @param {string} url
 * @param data
 * @param {import("axios").AxiosRequestConfig} [config]
 */
export function post(url, data, config) {
  return instance({ method: "post", url, data, ...config });
}

/**
 * @param url
 * @param {Object} [params]
 * @param {Object} [data]
 * @param {import("axios").AxiosRequestConfig} [config]
 */
export function postWithQueryParams(url, params, data, config) {
  return instance({ method: "post", url, params, data, ...config });
}

/**
 * @param {string} url
 * @param data
 * @param {import("axios").AxiosRequestConfig} [config]
 */
export function postForm(url, data, config) {
  return post(url, qs.stringify(data), {
    header: {
      "Content-Type": "application/x-www-form-urlencoded",
    },
    config,
  });
}

/**
 * @param {string} url
 * @param data
 * @param {import("axios").AxiosRequestConfig} [config]
 */
export function postFormData(url, data, config) {
  let formData;
  if (data instanceof FormData) {
    formData = data;
  } else {
    formData = new FormData();
    for (const key in data) {
      formData.append(key, data[key]);
    }
  }
  return post(url, formData, {
    header: {
      "Content-Type": "multipart/form-data",
    },
    timeout: 60000 * 10,
    ...config,
  });
}

/**
 * @param {string} url
 * @param data
 * @param {import("axios").AxiosRequestConfig} [config]
 */
export function del(url, data, config) {
  return instance({ method: "delete", url, data, ...config });
}

/**
 * @param {string} url
 * @param data
 * @param {import("axios").AxiosRequestConfig} [config]
 */
export function delForm(url, data, config) {
  return del(url, qs.stringify(data), {
    header: {
      "Content-Type": "application/x-www-form-urlencoded",
    },
    ...config,
  });
}

/**
 * @param {string} url
 * @param data
 * @param {import("axios").AxiosRequestConfig} [config]
 */
export function put(url, data, config) {
  return instance({ method: "put", url, data, ...config });
}

/**
 * @param {string} url
 * @param data
 * @param {import("axios").AxiosRequestConfig} [config]
 */
export function putForm(url, data, config) {
  return put(url, qs.stringify(data), {
    header: {
      "Content-Type": "application/x-www-form-urlencoded",
    },
    ...config,
  });
}

/**
 * @param {string} url
 * @param {import("axios").AxiosRequestConfig} [config]
 */
export function head(url, config) {
  return instance({ method: "head", url, ...config });
}
